﻿package com.htmlparser;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.tags.ScriptTag;
import org.htmlparser.util.NodeList;
import org.jdom.Document;

public class JavaScript_parser {
	static String path = "";
	static String html = "";
	static int scriptStart = 0;
	static String[] scripts;
	
	//解析JavaScript
	public static String getScript(String method, Object[] args){
		System.out.println("");
		System.out.println("###############  getScript开始  ################");
		System.out.println("");
		
		String result = "";
		NodeList scriptList = null;
		
		//提取当前页面所有的<script>标签   
		try {
			Parser parser = new Parser();
			parser.setInputHTML(html);	
			parser.setEncoding("GBK");
			NodeFilter scriptFilter = new NodeClassFilter(ScriptTag.class);
			scriptList = parser.extractAllNodesThatMatch(scriptFilter);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//获取数据源html里面所有的<script>的代码，存到一个String数组里面
		int numScript = scriptList.size();
		scripts = new String[numScript];
		for (int j = 0; j < scripts.length; j++) {
			scripts[j] = getScriptCode(html);
		}
		//scriptStart清零，保证下次循环正常
		scriptStart = 0;
		
		//遍历每个<script>标签的内容
		for (int i = 0; i < scriptList.size(); i++) {
			Node node = scriptList.elementAt(i);
			ScriptTag script = (ScriptTag)node;
			
			String code = "";
			String sys_path = "";
			
			//取得内部js的代码
			if ((script!= null) && (script.getAttributeEx("src")==null)) {
				//code = script.getScriptCode();
				
				code = scripts[i];
				
				//判断传过来的method是否在当前<script>标签内
				if (code.indexOf(method)>-1) {
					System.out.println("");
					//System.out.println("========== 【"+method+"】code: begain===========");
					//System.out.println(code);
					//System.out.println("========== 【"+method+"】code:  end ===========");
					System.out.println("");
					//取method方法的方法体content
					String content = Util.getMethodContent(code, method);
					//System.out.println("content:【" + content+"】");
					
					System.out.println("js的函数名：=="+method+"==");
					String[] parameters = Util.getJSParameters(code, method);
					for (int j = 0; j < parameters.length; j++) {
						System.out.println("funciton【"+method+"】的所有参数名：["+j+"]=="+parameters[j]+"==");
					}
					for (int j = 0; j < args.length; j++) {
						System.out.println("链接里的参数数组： ["+j+"]=="+args[j]+"==");
					}
					if(content.indexOf("return") == -1){
						if((parameters[0] == null) || (parameters.length == 0) || (parameters[0].equals(""))){
							//System.out.println("========== no return >>> no  parameters ==========");
							//没有return，没有参数
							System.out.println("no_return_if content==" + content + "==");
							result = JavaScript_parser.parseJs(content, args,parameters);
							//System.out.println("777777777777777 no return >>> no  parameters 777777777777");
						}else{
							//System.out.println("========== no return >>> have parameters ==========");
							//没有return，有参数
							System.out.println("no_return_else content==" + content + "==");
							result = JavaScript_parser.parseJs(content, args,parameters);
							//System.out.println("77777777777777 no return >>> have parameters 777777777777");
						}
					}else{
						if((parameters[0] == null) || (parameters.length == 0) || (parameters[0].equals(""))){
							//System.out.println("========== have return >>> no parameters ==========");
							System.out.println("return_if code==" + code + "==");
							result = JavaScript_parser.parseJs(code, method, args);

							//System.out.println("7777777777 have return >>> no parameters 777777777777");
						}else{
							//System.out.println("========== have return >>> have parameters ==========");
							System.out.println("return_else code99==" + code + "==");
							result = JavaScript_parser.parseJs(code, method, args);
							//System.out.println("777777777777 have return >>> have parameters 77777777777777");
						}
					}
					
					
//					if(content.indexOf("return") == -1){
//						if((args[0] == null) || (args.length == 0) || (args[0].equals(""))){
//							//System.out.println("========== no return >>> no  parameters ==========");
//
//							result = parseJs(content, args,parameters);
//
//							//System.out.println("777777777777777 no return >>> no  parameters 777777777777");
//						}else{
//							//System.out.println("========== no return >>> have parameters ==========");
//							result = parseJs(content, args,parameters);
//							//System.out.println("77777777777777 no return >>> have parameters 777777777777");
//						}
//					}else{
//						if((args[0] == null) || (args.length == 0) || (args[0].equals(""))){
//							//System.out.println("========== have return >>> no parameters ==========");
//
//							result = parseJs(code, method, args);
//
//							//System.out.println("7777777777 have return >>> no parameters 777777777777");
//						}else{
//							//System.out.println("========== have return >>> have parameters ==========");
//							result = parseJs(code, method, args);
//							//System.out.println("777777777777 have return >>> have parameters 77777777777777");
//						}
//					}
						break;
				}else {
					//result = "code not include the method:"+method+"()";
					continue;
				}
	
			}
			
			//取得外部js的路径
			if ((script!= null) && (script.getAttributeEx("src") != null)) {
				//System.out.println("script.getAttributeEx('src')==" + script.getAttributeEx("src")+"==");
					String src = script.getAttribute("src");
					src = src.replaceAll("/", "\\\\");
					sys_path = System.getProperty("user.dir") + src;
					//System.out.println("path: " + path);
					
						code = Util.ReadFile(sys_path);
						if (!code.equals("File not found")) {
							if (code.indexOf(method)>-1) {
								String content = Util.getMethodContent(code, method);
								
								if (content.indexOf("href")!= -1) {
									break;
								}
								else if (content.indexOf("window.open")!= -1) {
									break;
								}
								else {
									break;
								}
									
							} else {
								continue;
							}							
						} else {
							//result = "File not found";
							continue;
						}
			}
		}
		//System.out.println("getScript result: " + result);
		System.out.println("");
		System.out.println("################  getScript结束  ###############");
		System.out.println("");
		
		return result;
	}
	
	//解析JavaScript	
	public static String parseJs(String code, String method, Object[] args){
		System.out.println("");
		System.out.println("################  【parseJs-code】开始  #############");
		System.out.println("");
		
		String result = "";
		
		ScriptEngineManager factory = new ScriptEngineManager();
		ScriptEngine engine = factory.getEngineByName("JavaScript");
		
		Window window = new Window();
		Location location = new Location();
		com.htmlparser.Document document = new com.htmlparser.Document();
		History history = new History();
		Screen screen = new Screen();
		Parent parent = new Parent();
		Event event = new Event();
		
		engine.put("window", window);
		engine.put("location", location);
		engine.put("document", document);
		engine.put("history", history);
		engine.put("screen", screen);
		engine.put("parent", parent);
		engine.put("event", event);


		
		try {
			//System.out.println("8888888888888 content:"+content+"8888888888888888");
			engine.eval(code);
			Invocable invokeEngine = (Invocable) engine;
			//System.out.println("method:"+method);
			
			for(Object o:args){
				//System.out.println("args:"+o);
			}
			result = (String)invokeEngine.invokeFunction(method, args);
		      //System.out.println("JDK1.6 ----- result:"+result);

		} catch (Exception e) {
			//result = doScriptException2(e, engine, result, code, method, args);
		}
		
		if((result != null) && !(result.equals(""))){
			//如果路径是../开头
			if(String.valueOf(result.charAt(0)).equals(".")){
				result = result.substring(3, result.length());
				
				String html[] = path.split("/");
				StringBuffer url = new StringBuffer();
				for (int i = 0; i < html.length-1; i++) {
					System.out.println(html[i]);
					url.append(html[i] + "/");
				}
				result = url.toString() + result;
			}
			//如果路径前没有/
			else if(!(String.valueOf(result.charAt(0)).equals("/"))){
				result = path + result;
			}
		}
			
		System.out.println(" 【parseJs-code】返回的路径:=="+result+"==");
		System.out.println("");
		System.out.println("#############  【parseJs-code】结束  #################");
		System.out.println("");
	
		return result.replace(";", "");
	}
	

	//解析JavaScript	
	public static String parseJs(String content, Object[] args, Object[] parameters){
		System.out.println("");
		System.out.println("############# 【parseJs-content】开始  #################");
		System.out.println("");
		
		String result = "";
		
		ScriptEngineManager factory = new ScriptEngineManager();
		ScriptEngine engine = factory.getEngineByName("JavaScript");
		
		Window window = new Window();
		//Window.Location location = window.new Location();
		Location location = new Location();
		com.htmlparser.Document document = new com.htmlparser.Document();
		History history = new History();
		Parent parent = new Parent();
		Screen screen = new Screen();
		Event event = new Event();
		
		engine.put("window", window);
		engine.put("location", location);
		engine.put("document", document);
		engine.put("history", history);
		engine.put("screen", screen);
		engine.put("parent", parent);
		engine.put("event", event);
		
		//如果有参数，则在解析之前把参数和对应的值放入engine中
		if ((args != null)) {
			if ((parameters[0] != null) && !(parameters[0].equals(""))) {
				for (int i = 0; i < parameters.length && i < args.length; i++) {
					if ((parameters[i] != null) && !(parameters[i].equals(""))) {

						String temp = args[i].getClass().toString();
						String data_type = temp.substring(
								temp.lastIndexOf(".") + 1, temp.length());
						if (data_type.equals("String")) {
							engine.put(parameters[i].toString(),
									(String) args[i]);
						} else {
							engine.put(parameters[i].toString(), Float
									.parseFloat(String.valueOf(args[i])));
						}

					}

				}
			}
		}
		
		try {
			result = (String)engine.eval(content);
			if((result != null) && !(result.equals(""))){
				//如果路径是../开头
				if(String.valueOf(result.charAt(0)).equals(".")){
					result = result.substring(3, result.length());
					
					String html[] = path.split("/");
					StringBuffer url = new StringBuffer();
					for (int i = 0; i < html.length-1; i++) {
						System.out.println(html[i]);
						url.append(html[i] + "/");
					}
					result = url.toString() + result;
				}
				//如果路径前没有/
				else if(!(String.valueOf(result.charAt(0)).equals("/"))){
					result = path + result;
				}
			}
		} catch (Exception e) {
			//result = doScriptException(e, engine, result, content);
		}
		
		System.out.println(" 【parseJs-content】返回的路径:===="+result+"==");
		
		System.out.println("");
		System.out.println("###############  【parseJs-content】结束  #################");
		System.out.println("");
		
		return result.replace(";", "");
	}
	
	public static String doScriptException(Exception e, ScriptEngine engine, String result, String content){
		System.out.println("");
		System.out.println("XXXXXXXXXXXXXXXXXXXXXXX  Exception  begin XXXXXXXXXXXXXXXXXXXXXXXXX");
		System.out.println("");
		System.out.println("e.getMessage():" + e.getMessage());
		String exception = e.getMessage();
		int index = 0;
		int index1 = 0;
		int index2 = 0;
		index = exception.indexOf("ReferenceError:");
		if (index == -1) {
			index = exception.indexOf("property");
			if (index == -1) {
				index = exception.indexOf("named");
				if (index == -1) {
					index = exception.indexOf("named");
				}else {
					System.out.println("named");
				}
			}else {
				System.out.println("property");
			}
		} else{
			System.out.println("ReferenceError:");
		}
		
		if (index>0) {
			index1 = exception.indexOf("\"", index);
			index2 = exception.indexOf("\"", index1+1);
		}
		System.out.println("index:" + index);
		System.out.println("index1:" + index1);
		System.out.println("index2:" + index2);
		String keyword = "";
		if (index1 < index2) {
			keyword = exception.substring(index1+1, index2).trim();
			System.out.println("not defined==" + keyword + "==");
		}
		engine.put(keyword, keyword);
		engine.put("form1", "form1");
		engine.put("mytextfield", "mytextfield");
		try {
			result = (String)engine.eval(content);
			System.out.println("doScriptException---result==" + result + "==");
		} catch (Exception e1) {
			//result = doScriptException(e1, engine, result, content);
			e1.printStackTrace();
		}
		System.out.println("");
		System.out.println("XXXXXXXXXXXXXXXXXXXXXXX  Exception  end XXXXXXXXXXXXXXXXXXXXXXXXXXX");
		System.out.println("");
		System.out.println("doScriptException---result22222222222==" + result + "==");
		
		//String应该是传引用的，这里修改的result与调用该方法的parseJs的result是同一个，但是如果不把这里的result返回，那么parseJs的result将为空，奇怪。。。
		return result;
	}

	public static String doScriptException2(Exception e, ScriptEngine engine, String result, String code, String method, Object[] args){
		System.out.println("");
		System.out.println("XXXXXXXXXXXXXXXXXXXXXXX  Exception  begin XXXXXXXXXXXXXXXXXXXXXXXXX");
		System.out.println("");
		System.out.println("e.getMessage():" + e.getMessage());
		String exception = e.getMessage();
		int index = 0;
		int index1 = 0;
		int index2 = 0;
		index = exception.indexOf("ReferenceError:");
		if (index == -1) {
			index = exception.indexOf("property");
			if (index == -1) {
				index = exception.indexOf("named");
				if (index == -1) {
					index = exception.indexOf("named");
				}else {
					System.out.println("named");
				}
			}else {
				System.out.println("property");
			}
		} else{
			System.out.println("ReferenceError:");
		}
		
		if (index>0) {
			index1 = exception.indexOf("\"", index);
			index2 = exception.indexOf("\"", index1+1);
		}
		System.out.println("index:" + index);
		System.out.println("index1:" + index1);
		System.out.println("index2:" + index2);
		String keyword = "";
		if (index1 < index2) {
			keyword = exception.substring(index1+1, index2).trim();
			System.out.println("not defined==" + keyword + "==");
		}
		engine.put(keyword, keyword);
		try {
			engine.eval(code);
			Invocable invokeEngine = (Invocable) engine;
			//System.out.println("method:"+method);
			
			for(Object o:args){
				//System.out.println("args:"+o);
			}
			result = (String)invokeEngine.invokeFunction(method, args);
		} catch (Exception e1) {
			//result = doScriptException2(e1, engine, result, code, method, args);
			e1.printStackTrace();
		}
		System.out.println("");
		System.out.println("XXXXXXXXXXXXXXXXXXXXXXX  Exception  end XXXXXXXXXXXXXXXXXXXXXXXXXXX");
		System.out.println("");
		return result;
	}
	
	//提取<script>与</script>之间的代码
	public static String getScriptCode(String html){
		System.out.println("@@@@@@@@@@@@@@@@@@@ getScriptCode begain @@@@@@@@@@@@@@@@@");
		//System.out.println("scriptStart=" + scriptStart);
		String script = "";
		int b1 = html.indexOf("<script", scriptStart);
		System.out.println("b1=" + b1);
		if (b1 == -1) {
			b1 = html.indexOf("<SCRIPT", scriptStart);
		}
		if (b1 != -1) {
			int b2 = html.indexOf(">", b1);
			int b3 = html.indexOf("</script>", b2);
			if (b3 == -1) {
				b3 = html.indexOf("</SCRIPT>", b2);
			}
			script = html.substring(b2+1, b3);
			scriptStart = b3;
			System.out.println("b3=" + b3);
		}
		System.out.println("");
		//System.out.println(script);
		System.out.println("@@@@@@@@@@@@@@@@@@@ getScriptCode end @@@@@@@@@@@@@@@@@");
		return script;
	}
}
